package com.chen.apply.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.apply.feign.ApprovalServiceClient;
import com.chen.apply.mapper.ApplyMapper;
import com.chen.apply.mapper.PlanMapper;
import com.chen.apply.mapper.ReimburseMapper;
import com.chen.apply.service.ApplyService;
import com.common.pojo.entity.Apply;
import com.common.pojo.entity.Plan;
import com.common.pojo.entity.Reimburse;
import com.common.pojo.req.ApplyUpdateReqDTO;
import com.common.pojo.req.ApplySubmitReqDTO;
import com.common.pojo.resp.ApplyEditRespDTO;
import com.common.pojo.resp.ApplyInquiryRespDTO;
import com.common.pojo.resp.ApprovalRecordRespDTO;
import com.common.pojo.resp.PageResult;
import com.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ApplyServiceImpl extends ServiceImpl<ApplyMapper, Apply> implements ApplyService {


    @Autowired
    PlanMapper planMapper;
    @Autowired
    ApplyMapper applyMapper;
    @Autowired
    ReimburseMapper reimburseMapper;
    @Autowired
    private ApprovalServiceClient approvalServiceClient;

    @Override
    public boolean submitApply(ApplySubmitReqDTO applyReqDTO) {

        // 1. 生成申请单号
        String applyId = generateApplyId();
        Apply apply = new Apply();

        // 2. 构建 Apply 实体并保存
        BeanUtils.copyProperties(applyReqDTO, apply);
        apply.setApplyId(applyId);
        apply.setCreateTime(LocalDateTime.now());
        apply.setUpdateTime(LocalDateTime.now());

        boolean applySaved = this.save(apply);

        if (!applySaved) {
            throw new RuntimeException("保存申请信息失败");
        }

        // 3. 保存行程计划
        if (applyReqDTO.getPlans() != null && !applyReqDTO.getPlans().isEmpty()) {
            boolean plansSaved = savePlans(applyReqDTO.getPlans(), apply.getId());
            if (!plansSaved) {
                throw new RuntimeException("保存行程计划失败");
            }
        }

        return true;
    }

    @Override
    public PageResult<ApplyInquiryRespDTO> getApplyInquiryRespDTO(LocalDate leftTime, LocalDate rightTime, int pageNum, int pageSize) {
        // 1. 构建查询条件
        LambdaQueryWrapper<Apply> queryWrapper = new LambdaQueryWrapper<Apply>()
                .between(Apply::getStartTime, leftTime, rightTime)
                .orderByDesc(Apply::getCreateTime);

        // 2. 创建分页对象
        Page<Apply> page = new Page<>(pageNum, pageSize);

        // 3. 执行分页查询
        Page<Apply> applyPage = applyMapper.selectPage(page, queryWrapper);

        List<Apply> applies = applyPage.getRecords();
        Long total = applyPage.getTotal();

        log.info("分页查询结果 - 当前页: {}, 每页大小: {}, 总记录数: {}, 当前页记录数: {}",
                pageNum, pageSize, total, applies.size());

        if (applies.isEmpty()) {
            return new PageResult<>(Collections.emptyList(), total);
        }

        // 4. 转换为DTO列表
        List<ApplyInquiryRespDTO> dtoList = applies.stream().map(apply -> {
            ApplyInquiryRespDTO dto = new ApplyInquiryRespDTO();
            BeanUtils.copyProperties(apply, dto);
            // 设置总预算金额
            dto.setTotalBudgetAmount(planMapper.selectTotalBudgetByApplyId(apply.getId()));
            // 设置总报销金额
            dto.setTotalReimburseAmount(reimburseMapper.selectTotalReimburseByApplyId(apply.getId()));
            return dto;
        }).collect(Collectors.toList());

        return new PageResult<>(dtoList, total);
    }

    @Override
    public Integer getStatusByApplyId(Integer applyId) {
        Apply apply = this.getById(applyId);
        return apply != null ? apply.getStatus() : null;
    }

    @Override
    public boolean updateApply(ApplyUpdateReqDTO editReqDTO) {
        Apply apply = new Apply();
        BeanUtils.copyProperties(editReqDTO, apply);
        apply.setUpdateTime(LocalDateTime.now());
        boolean applyUpdated = this.updateById(apply);
        if (!applyUpdated) {
            throw new RuntimeException("更新申请信息失败");
        }

        if (editReqDTO.getPlans() != null) {
            boolean plansUpdated = updatePlans( editReqDTO.getPlans(),apply.getId());
            if (!plansUpdated) {
                throw new RuntimeException("更新行程计划失败");
            }
        }

        return true;
    }

    @Override
    public ApplyEditRespDTO getApplyEditData(Integer applyId) {
        // 1. 获取申请基本信息
        Apply apply = this.getById(applyId);
        if (apply == null) {
            throw new RuntimeException("申请不存在");
        }

        // 2. 获取该申请的行程计划
        List<Plan> plans = planMapper.selectList(
                new QueryWrapper<Plan>().eq("apply_id", applyId).orderByAsc("id")
        );

        ApplyEditRespDTO dto = new ApplyEditRespDTO();
        BeanUtils.copyProperties(apply,dto);

        dto.setPlans(plans);
        // 3. 构建返回DTO
        return dto;
    }


    /**
     * 更新行程计划
     */
    private boolean updatePlans(List<Plan> plans, Integer id) {
        List<Integer> planIds = new ArrayList<>();
        for (Plan plan : plans) {
            plan.setApplyId(id);
            planIds.add(plan.getId());
        }

        // 删除不在 planIds 里的行程计划
        if (!planIds.isEmpty()) {
            // 删除不在 planIds 里的行程计划

            LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<Plan>()
                                                    .notIn(Plan::getId,planIds)
                                                    .eq(Plan::getApplyId,id);
            planMapper.delete(queryWrapper);

            // 删除不在 planIds 里的报销项
            LambdaQueryWrapper<Reimburse> reimburseWrapper = new LambdaQueryWrapper<Reimburse>()
                    .eq(Reimburse::getApplyId,id)
                    .notIn(Reimburse::getPlanId,planIds);
            reimburseMapper.delete(reimburseWrapper);
        } else {
            // 如果 planIds 为空，删除所有相关计划和报销
            LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<Plan>()
                    .eq(Plan::getApplyId,id);
            planMapper.delete(queryWrapper);

            QueryWrapper<Reimburse> deleteReimburseWrapper = new QueryWrapper<>();
            reimburseMapper.delete(deleteReimburseWrapper);
        }

        log.info("plans: {}",plans);
        // 处理新增和更新
        for (Plan plan : plans) {
            if (plan.getId() == null) {
                // 插入新计划
                log.info("插入: {}",plan);
                planMapper.insert(plan);
            } else {
                // 更新现有计划
                planMapper.updateById(plan);
            }
        }



        return true;
    }

    /**
     * 生成申请单号 (TR-YYYYMMDD-XXXX 格式)
     */
    private String generateApplyId() {
        LocalDate today = LocalDate.now();
        String datePart = today.format(DateTimeFormatter.ofPattern("yyyyMMdd"));

        // 查询今日已有申请数量
        long count = this.count(new QueryWrapper<Apply>()
                .likeRight("apply_id", "TR-" + datePart));

        String sequence = String.format("%04d", count + 1);
        return "TR-" + datePart + "-" + sequence;
    }


    /**
     * 保存行程计划列表
     */
    private boolean savePlans(List<Plan> plans, Integer applyId) {
        for (Plan plan : plans) {
            plan.setApplyId(applyId); // 设置关联的申请ID
            int result = planMapper.insert(plan);
            if (result <= 0) {
                return false;
            }
        }
        return true;
    }



    /**
     * 从审核模块获取审核记录
     */
    @Override
    public List<ApprovalRecordRespDTO> getApprovalRecordsFromApprovalService(Long applyId) {
        try {
            log.info("调用审核服务获取申请 {} 的审核记录", applyId);

            Result<List<ApprovalRecordRespDTO>> result =
                    approvalServiceClient.getApprovalRecordsByApplyId(applyId);

            if (result.getCode() == 200 && result.getData() != null) {
                log.info("成功从审核服务获取到 {} 条审核记录", result.getData().size());
                return result.getData();
            } else {
                return Collections.emptyList();
            }
        } catch (Exception e) {
            log.error("调用审核服务失败: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
}
